package com.hc.core.web.springmvc;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver;

import com.hc.core.web.token.TokenProcessor;

/**
 * 说明：前端处理层的基类，基于spring的MultiActionController。建议处理层对象继承该类。<br>
 * 有如下几个功能： <br>
 * <ol>
 * <li>提供了缺省的解析参数名称和缺省处理方法，根据传来的参数决定调用哪个处理方法。 解析参数名和缺省处理方法名也可重新设定。<br>
 * <b>请注意：</b>缺省处理方法名对应的方法必须在之类实现，否则解析参数没有值时会出错。 </li>
 * <li>提供一个方法showMessage()，用来向客户端显示消息。 </li>
 * <li>提供了错误处理机制，如果请求处理过程中发生错误，且用户没有处理，则会自动调用出错显示页面，显示给用户。</li>
 * <li>提供了类型转换注册入口，对于数值，日期等不能自动转换的类型，允许注册特定类型转换器进行转换。<br>
 * <b>注意 </b>：如果在从request参数到VO对象的绑定过程发生错误。程序会忽略，继续向下进行。 <br>
 * (因为我发现绑定错误都是由于类型转换错误引起的，像日期，数字类型，如果传来的是"",会发生错误。 其实这种情况是允许的。) <br>
 * </li>
 * <li>提供了param2Object()方法，用来手动将传来的参数设置进指定VO对象。(CURD子类的方法更方便)</li>
 * <li>增加参数前缀prefix和分隔符prefixSeparator，用来处理传来的参数有前缀的情况。默认参数有前缀p_，设置prefix=null可以去掉前缀。</li>
 * <li>提供令牌token处理功能，可以实现对特定请求生成令牌(generateToken,saveToken)，校验令牌(isTokenValid)，重置令牌(resetToken)等功能。</li>
 * <li>若参数defaultCheckToken=true，则默认处理令牌：对get请求会生成新的token，对post请求会校验其token值。也可不自动处理token，由子类自行处理。</li>
 * </ol>
 * 
 * 该类的处理方法我们常用以下两种定义形式： <br>
 * <ul>
 * <li>ModelAndView XX(HttpServletRequest request, HttpServletResponse
 * response); <br>
 * 这是最通用的方法，用来处理简单的，不需要自动类型转换的情况。推荐使用！<br>
 * 如果需要将传来的参数设置进指定对象，可以使用param2Object()方法实现。 </li>
 * <li>ModelAndView XX(HttpServletRequest request, HttpServletResponse
 * response,VOObject vo); <br>
 * 这个方法可以自动将传来的参数转换成VO对象供使用，如同SimpleFormController所做的一样。 </li>
 * </ul>
 * 
 */
public class BaseController extends MultiActionController implements
		InitializingBean {

	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(BaseController.class);

	// 令牌处理器
	private static TokenProcessor token = TokenProcessor.getInstance();

	public static final String DEFAULT_PREFIX = "p";

	public static final String DEFAULT_PREFIX_SEPARATOR = "_";

	private static String DEFAULT_METHOD_NAME = "index"; // 缺省调用的处理方法

	private static String DEFAULT_PARAM_NAME = "action"; // 缺省依据的解析参数的名称

	protected static String DEFAULT_PAGE_ON_ERROR = "error"; // 缺省出错时显示的页面

	protected static String DEFAULT_PAGE_ON_SESSIONTIMEOUT = "sessiontimeout";// session超时

	private String defaultMethodName = DEFAULT_METHOD_NAME; // 缺省调用的处理方法

	private String paramName = DEFAULT_PARAM_NAME; // 依据的解析参数名

	protected String errorPage = DEFAULT_PAGE_ON_ERROR;

	protected String sessiontimeoutPage = DEFAULT_PAGE_ON_SESSIONTIMEOUT;

	private String prefix = DEFAULT_PREFIX; // 参数前缀

	private String prefixSeparator = DEFAULT_PREFIX_SEPARATOR; // 参数前缀与参数之间的分隔符

	protected boolean defaultCheckToken = false; // 是否需要对请求进行令牌校验

	/**
	 * 
	 * 空构造方法
	 */
	public BaseController() {
		super();

	}

	/**
	 * 初始化方法，设置解析参数名和缺省的调用方法
	 * 
	 * @throws Exception
	 */
	public void afterPropertiesSet() throws Exception {
		// 设置缺省的方法解析类
		ParameterMethodNameResolver nameResolver = new ParameterMethodNameResolver();
		nameResolver.setParamName(this.paramName);
		nameResolver.setDefaultMethodName(this.defaultMethodName);
		this.setMethodNameResolver(nameResolver);
	}
}